package com.ruoyi.flowable.listener.repair;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.equ.domain.EquAsset;
import com.ruoyi.equ.domain.EquRepair;
import com.ruoyi.equ.service.IEquAssetService;
import com.ruoyi.equ.service.IEquRepairService;
import com.ruoyi.flowable.service.IWorkOrderAssetRelService;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysNoticeService;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 维修2-派工监听
 */
@Slf4j
@Component("repairAssignListener")
public class RepairAssignListener implements ExecutionListener {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final IEquRepairService repairService = SpringUtils.getBean(IEquRepairService.class);
    private static final IEquAssetService assetService = SpringUtils.getBean(IEquAssetService.class);
    private static final ISysDeptService deptService = SpringUtils.getBean(ISysDeptService.class);
    private static final ISysUserService userService = SpringUtils.getBean(ISysUserService.class);
    private static final ISysNoticeService noticeService = SpringUtils.getBean(ISysNoticeService.class);
    private static final IWorkOrderAssetRelService workOrderAssetRelService = SpringUtils.getBean(IWorkOrderAssetRelService.class);
    private static final String REPAIR_NOTICE_TITLE = "维修工单处理提醒";
    private static final String DEPT_OVERTIME_TITLE = "维修工单处理超时提醒";

    @Override
    public void notify(DelegateExecution execution) {
        try {
            //维修执行信息：派工部门+负责人
            String deptId = execution.getVariable("assignDept", String.class);
            String assignDept = deptService.selectDeptById(Long.valueOf(deptId)).getDeptName();
            //数字类型转String TODO 前端转选择框需要转为String
            String userId = execution.getVariable("leader", Integer.class).toString();
            String leader = userService.selectUserById(Long.valueOf(userId)).getNickName();
            String leaderPhone = execution.getVariable("leaderPhone", String.class);
            String assignDate = execution.getVariable("assignDate", String.class);
            String willTime = execution.getVariable("willTime", String.class);

            HashMap<String, Object> repairExecMap = new HashMap<>();
            repairExecMap.put("派工部门", assignDept);
            repairExecMap.put("维修负责人", leader);
            repairExecMap.put("联系电话", leaderPhone);
            repairExecMap.put("派工日期", assignDate);
            repairExecMap.put("预计完成时间", willTime);
            String repairExec = objectMapper.writeValueAsString(repairExecMap);

            //工单最终状态：维修中
            String orderStatus = "维修中";
            //updateBy
            String updateBy = SecurityUtils.getLoginUser().getUser().getNickName();
            EquRepair equRepair = execution.getVariable("equRepair", EquRepair.class);
            equRepair.setRepairExec(repairExec);
            equRepair.setOrderStatus(orderStatus);
            equRepair.setUpdateBy(updateBy);
            //修改
            repairService.updateEquRepair(equRepair);
            //json
            execution.setVariable("equRepair", equRepair);

            //修改asset状态
            EquAsset equAsset = new EquAsset();
            equAsset.setAssetId(Long.valueOf(execution.getVariable("assetId", String.class)));
            equAsset.setAssetStatus(orderStatus);
            assetService.updateEquAsset(equAsset);

            //提醒维修负责人员
            noticeWorker(equRepair, execution);

            //更新状态
            String processInstanceId = execution.getProcessInstanceId();
            workOrderAssetRelService.updateWorkOrderStatus(processInstanceId, "处理中", null);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    //提醒负责人
    private void noticeWorker(EquRepair equRepair, DelegateExecution execution) {
//        //获取发布人id
//        Long publishId = SecurityUtils.getUserId();
//        //获取发布人名称
//        String publishName = SecurityUtils.getUsername();

        //获取维修负责人id
        //数字类型转String TODO 前端转选择框需要转为String
        Long userId = Long.valueOf(execution.getVariable("leader", Integer.class).toString());
        String userName = userService.selectUserById(userId).getUserName();
        Long deptId = Long.valueOf(execution.getVariable("assignDept", String.class));
        SysDept sysDept = deptService.selectDeptById(deptId);
        //部门负责人
        String leader = sysDept.getLeader();
        SysUser sysUser = userService.selectUserByUserName(leader);
        Long leaderId = sysUser.getUserId();

        //创建定时任务
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        long initialDelay = 0; // 初始延迟：0分钟（立即开始第一次执行）
        long period = 30;      // 执行周期：30分钟
        long totalDuration = 120; // 总执行时长：2小时
        TimeUnit timeUnit = TimeUnit.MINUTES; // 时间单位：分钟
        //获取通知对象
        SysNotice notice = new SysNotice();
        notice.setPublishId(0L);
        notice.setPublishName("系统");
        //线程池，紧急工单，注意判断工单是否响应(该工单状态变为维修中)
        String urgency = execution.getVariable("urgency", String.class);
        if (urgency.equals("紧急")) {
            // 30分钟后执行逻辑 提醒维修负责人
            scheduler.scheduleAtFixedRate(() -> {
                //查询状态是否响应
                EquRepair equRepair1 = repairService.selectEquRepairByRepairId(equRepair.getRepairId());
                if (equRepair1.getOrderStatus().equals("已完成")) {
                    scheduler.shutdown();
                } else {
                    notice.setAcceptId(userId);
                    notice.setNoticeTitle(REPAIR_NOTICE_TITLE);
                    notice.setNoticeContent("工单编号：" + equRepair.getRepairId() + "，请及时处理！");
                    noticeService.insertNotice(notice);
                }
            }, initialDelay, period, timeUnit);
            // 2小时后执行逻辑 提醒部门负责人
            scheduler.schedule(() -> {
                EquRepair equRepair1 = repairService.selectEquRepairByRepairId(equRepair.getRepairId());
                if (equRepair1.getOrderStatus().equals("已完成")) {
                    //关闭线程池
                    scheduler.shutdown();
                } else {
                    notice.setAcceptId(leaderId);
                    notice.setNoticeTitle(DEPT_OVERTIME_TITLE);
                    notice.setNoticeContent("工单编号：" + equRepair.getRepairId() +
                            "处理超时，部门负责人请及时联系维修负责人:" + userName);
                    noticeService.insertNotice(notice);
                }
            }, totalDuration, timeUnit);
        }
    }
}
